

#include <gfx/gl20/vertexbuffer_gl15.h>

static GLuint current_mapped_buffer = 0;

ceVertexBufferGL15::ceVertexBufferGL15 ()
  : name(0)
{
  CE_OBJECT_CONSTR
}

ceVertexBufferGL15::~ceVertexBufferGL15 ()
{
  if (name)
  {
    glDeleteBuffers (1, &name);
  }
}
static inline GLenum ConvertBufferAccessMode (ceBufferAccessMode mode)
{
  switch (mode)
  {
  case BAM_Read:
    return GL_READ_ONLY;
  case BAM_Write:
    return GL_WRITE_ONLY;
  case BAM_ReadWrite:
    return GL_READ_WRITE;
  }
  return GL_READ_WRITE;
}

static inline GLenum ConvertBufferDataMode (ceBufferDataMode mode)
{
  switch (mode)
  {
  case BDM_Dynamic:
    return GL_DYNAMIC_DRAW;
  case BDM_Static:
    return GL_STATIC_DRAW;
  case BDM_Stream:
    return GL_STREAM_DRAW;
  }
  return GL_STATIC_DRAW;
}

bool ceVertexBufferGL15::CreateBuffer (unsigned size, const void* data, ceBufferDataMode mode)
{
  glGenBuffers (1, &name);
  if (name == 0)
  {
    return false;
  }

  glBindBuffer(GL_ARRAY_BUFFER, name);
  glBufferData (GL_ARRAY_BUFFER, size, data, ConvertBufferDataMode(mode));

  return true;
}

bool ceVertexBufferGL15::Copy (unsigned offset, unsigned size, const void* data)
{
  if (name == 0)
  {
    return false;
  }

  glBindBuffer (GL_ARRAY_BUFFER, name);
  glBufferSubData (GL_ARRAY_BUFFER, offset, size, data);
  return true;
}

bool ceVertexBufferGL15::Lock (unsigned offset, void** data, ceBufferAccessMode mode)
{
  if (name == 0 || current_mapped_buffer != 0)
  {
    return false;
  }

  void *res = 0;
  glBindBuffer (GL_ARRAY_BUFFER, name);
  res = glMapBuffer (GL_ARRAY_BUFFER, ConvertBufferAccessMode(mode));
  if (!res)
  {
    return false;
  }
  current_mapped_buffer = name;
  // now map the offset
  *data = &((char*)res)[offset];
  return true;
}

bool ceVertexBufferGL15::Unlock ()
{
  if (name == 0 || current_mapped_buffer != name)
  {
    return false;
  }

  glUnmapBuffer (GL_ARRAY_BUFFER);

  current_mapped_buffer = 0;
  return true;
}

void* ceVertexBufferGL15::Bind ()
{
  glBindBuffer(GL_ARRAY_BUFFER, name);
  return 0;
}
